<template>
  <view class="un-preview-img-container" v-if="showVal" :style="[containerStyle]">
    <!-- 顶部插槽 -->
    <slot name="top">
      <!-- 顶部工具栏 -->
      <view class="top-default-tools">
        <!-- 顶部左侧插槽 -->
        <slot name="top-left">
          <!-- 顶部右侧数字 -->
          <view class="current-num">
            <text class="current-num-text">{{ currentNum }}</text>
          </view>
        </slot>
        <!-- 顶部右侧插槽 -->
        <slot name="top-right">
          <!-- 顶部右侧菜单 -->
          <view class="top-menu" @click="handleMenuClick">
            <view class="top-menu-icon">
              <view class="top-menu-icon-item"></view>
              <view class="top-menu-icon-item"></view>
              <view class="top-menu-icon-item"></view>
            </view>
          </view>
        </slot>
      </view>
    </slot>
    <!-- 图片swiper -->
    <swiper class="img-swiper"
            :current="currentIndex"
            :disable-touch="swiperDisabled"
            @change="handleSwiperChange"
            @transition="handleSwiperTransition"
            @animationfinish="handleSwiperAnimationFinish">
      <swiper-item
        class="img-swiper-item"
        v-for="(item, index) in urls"
        :key="index">
        <!-- 图片项，包含移动、缩放 -->
        <un-preview-image-item
          ref="unPreviewImgItem"
          :data="item"
          :index="index"
          :img-field="imgField"
          :disabled="swiperMoving"
          :system-info="systemInfo"
          @click="handleItemClick"
          @scale="handleItemScale">
        </un-preview-image-item>
      </swiper-item>
    </swiper>
    <slot name="bottom"></slot>
  </view>
</template>

<script>
import UnPreviewImageItem from "./un-preview-image-item.vue";
import {save} from "../../libs/util/save";

export default {
  name: 'UnPreviewImage',
  // #ifdef MP-WEIXIN
  options: {
    virtualHost: true
  },
  // #endif
  components: {UnPreviewImageItem},
  props: {
    // 预览背景
    bgColor: {
      type: String,
      default: '#000'
    },
    // 层级
    zIndex: {
      type: Number,
      default: 999
    },
    // 图片字段名，用于在urls为对象数组时指定字段名，不指定则用于匹配字符串数组项（此时indexOrUrl必须为urls中的某一项）
    imgField: {
      type: String
    },
    // 最小缩放
    scaleMin: {
      type: Number,
      default: 1
    },
    // 最大缩放
    scaleMax: {
      type: Number,
      default: 3
    },
  },
  data() {
    return {
      // 图片地址集
      urls: [],
      // 当前图片下标
      currentIndex: 0,
      // 是否显示
      showVal: false,
      // 是否禁用swiper，用于解决movable-area与swiper冲突
      swiperDisabled: false,
      // swiper是否正在移动，用于在swiper移动时禁用缩放与拖拽
      swiperMoving: false,
      systemInfo: null
    }
  },
  computed: {
    // 右上角显示的数字，当前/总
    currentNum() {
      return `${this.currentIndex + 1}/${this.urls.length}`
    },
    // 预览容器的样式
    containerStyle() {
      const style = {
        background: this.bgColor || '#000',
        zIndex: this.zIndex || 999,
      }
      return style
    },
  },
  methods: {
    // 显示预览
    show(urls, indexOrUrl = 0) {
      // 初始化信息
      this.swiperDisabled = false
      this.swiperMoving = false

      this.systemInfo = uni.getSystemInfoSync()
      this.urls = urls || []
      const maxIndex = this.urls.length - 1
      if (typeof indexOrUrl === 'number') {
        this.currentIndex = Math.min(indexOrUrl, maxIndex)
      } else {
        // 如果是字符串，则根据图片地址查找
        let index = -1;
        for (let i = 0; i < this.urls.length; i++) {
          const item = this.urls[i]
          if (this.imgField) {
            if (item[this.imgField] === indexOrUrl) {
              index = i
              break
            }
          } else {
            if (item === indexOrUrl) {
              index = i
              break
            }
          }
        }
        if (index !== -1) {
          this.currentIndex = index
        } else {
          this.currentIndex = 0
        }
      }
      this.showVal = true
    },
    // 关闭预览
    close() {
      this.showVal = false
    },
    /**
     * 如果已打开则关闭，并返回原本的打开状态
     *
     * 一般用于返回键关闭预览
     *
     * @example
     * ```js
     * onBackPress() {
     *     // 返回时如果当前为打开转态，则则关闭并阻止返回
     *     if (this.$refs.unPreImg.closeIfOpen()) {
     *       return true;
     *     }
     *     return false;
     * }
     * ```
     * @returns {boolean} 原本的打开状态
     */
    closeIfOpen() {
      let isOpen = false
      if (this.showVal) {
        this.showVal = false
        isOpen = true
      }
      return isOpen
    },
    // 监听菜单点击
    handleMenuClick() {
      this.$emit('menu', this.urls[this.currentIndex])
    },
    // 监听swiper变化
    handleSwiperChange(e) {
      // 修改当前下标
      this.currentIndex = e.detail.current
    },
    // 监听swiper-item的位置发生改变时会
    handleSwiperTransition() {
      this.swiperMoving = true
    },
    handleSwiperAnimationFinish() {
      // 修改swiper禁用状态
      this.swiperDisabled = this.$refs.unPreviewImgItem[this.currentIndex].scaleVal > 1
      // 退出swiper移动中
      this.swiperMoving = false
    },
    // 监听数据项点击
    handleItemClick() {
      this.$emit('item-click', this.urls[this.currentIndex])
    },
    handleItemScale(scale) {
      // 修改swiper禁用状态
      this.swiperDisabled = scale > 1
    },
    save(url) {
      return save(url)
    }
  }
}
</script>

<style lang="scss" scoped>
.un-preview-img-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: #000;

  // 顶部工具栏
  .top-default-tools {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10;
    padding: 60rpx 40rpx 40rpx;
    box-sizing: border-box;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.4) 70%, transparent 100%);

    // 左上角数字
    .current-num {

      &-text {
        color: #fff;
        font-size: 16px;
        font-weight: 500;
      }
    }

    // 右上角菜单
    .top-menu {
      &-icon {
        display: flex;
        flex-direction: row;

        &-item {
          width: 4px;
          height: 4px;
          background-color: #fff;
          border-radius: 50%;
          margin-left: 6px;
        }
      }
    }
  }

  // 图片swiper
  .img-swiper {
    width: 100%;
    height: 100%;

    &-item {
      width: 100%;
      height: 100%;
    }
  }
}
</style>
